package wubj.com.uploaddemo.upload;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import wubj.com.uploaddemo.application.MyApplication;
import wubj.com.uploaddemo.bean.ChatMsg;
import wubj.com.uploaddemo.utils.LogUtil;

public class UploadManager {

    private static final String TAG = UploadManager.class.getSimpleName();

    public static final int UNKNOWN = -2; // Unknown task

    private int maxNumber = DownConstants.taskMaxNumber;

    private Vector<UploadTask> mTasks = new Vector<UploadTask>(
            16);
    private HashMap<Long, UploadTask> mDoingTasks = new HashMap<>(maxNumber);// Downloading task
    private HashMap<String, UploadTask> mDoingImgTasks = new HashMap<String, UploadTask>(
            3);// Downloading Picture task
    private HashMap<Long, UploadTask> mPauseTasks = new HashMap<>(); // suspend
    // task
    private DownloadObserver downloadObserver;
    private String URL_DOWNLOAD;
    private FileUploadDb mFileUploadDb;

    public UploadManager() {
        downloadObserver = new DownloadObserver();
        mFileUploadDb = new FileUploadDb(MyApplication.mContext);
    }

    public void addTask(ChatListAidl uploadList, IuploadListener listener) {
        ArrayList<ChatMsg> req = uploadList.respList;
        int position = 0;
        for (ChatMsg info : req) {
            LogUtil.d(TAG, "wubaojie>>>addTask: info.id:" + info.msgId + " filename:" + info.fileName);
            if (!isExist(info.msgId)) {
                UploadThread thread = new UploadThread(info, this);
                thread.status = DownConstants.START;
                downloadObserver.addObserver(thread);
                mTasks.add(new UploadTask(position++, info.msgId, thread, listener));
                mFileUploadDb.insertOrUpdateMsg(info);
            } else {
                setCallback(info.msgId, listener);
            }
        }
        doTask();
    }


//    public void addTask(ChatListAidl uploadList, IUploadCallback uploadCallback) {
//        ArrayList<ChatMsg> req = uploadList.respList;
//        int position = 0;
//        for (ChatMsg info : req) {
//            LogUtil.d(TAG, "wubaojie>>>addTask: info.id:" + info.msgId + " filename:" + info.fileName);
//            if (!isExist(info.msgId)) {
//                UploadThread thread = new UploadThread(info, this);
//                thread.status = DownConstants.START;
//                downloadObserver.addObserver(thread);
//                mTasks.add(new UploadTask(position++, info.msgId, thread, uploadCallback));
//                mFileUploadDb.insertOrUpdateMsg(info);
//            } else {
//                setCallback(info.msgId, uploadCallback);
//            }
//        }
//        doTask();
//    }

    private boolean isExist(long id) {
        boolean isExist = false;
        UploadTask task;
        task = getTask(id, false);
        if (task != null) {
            isExist = true;
        } else {
            task = getDoingTask(id, false);
            if (task != null) {
                isExist = true;
            } else {
                task = getPauseTask(id, false);
                if (task != null) {
                    isExist = true;
                }
            }
        }
        return isExist;
    }

    private void addTask(UploadTask task) {
        mTasks.add(task);
        doTask();
    }

    private void doTask() {
        LogUtil.d(TAG, "wubaojie>>>doTask: " + (!mTasks.isEmpty() && mTasks.size() > 0));
        if (!mTasks.isEmpty() && mTasks.size() > 0) {
            UploadTask info;
            LogUtil.d(TAG, "wubaojie>>>doTask: mTasks.size():" + mTasks.size());
            for (int j = 0; j < mTasks.size(); j++) {
                info = mTasks.get(j);
                if (mDoingTasks.size() < maxNumber) {
                    int min = Math.min(mTasks.size(), maxNumber - mDoingTasks.size());
                    LogUtil.d(TAG, "wubaojie>>>doTask: min:" + min);
                    UploadTask task;
                    for (int i = 0; i < min; i++) {
                        info.downloadThread.downType = false;
                        task = mTasks.remove(0);
                        mDoingTasks.put(task.id, task);
                        task.downloadThread.resume();
                    }
                }
            }
        }
    }

    public ChatListAidl findMsgList(String fromUserId, String toUserId) {
        return new ChatListAidl(mFileUploadDb.findMsgList(fromUserId, toUserId));
    }

    public void deleteMsg(long msgId) {
        mFileUploadDb.deleteMsg(msgId);
    }

    public void pause(long id) {
        UploadTask task = getTask(id, true);
        if (task != null) {
            mPauseTasks.put(task.id, task);
        } else {
            task = getDoingTask(id, true);
            if (task != null) {
                task.downloadThread.pause();
                mPauseTasks.put(task.id, task);
            }
        }
    }

    public int getStatus(long id) {
        UploadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getStatus();
        }
    }

    public float getProgress(long id) {
        UploadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getProgress();
        }
    }

    public long getDowned(long id) {
        UploadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getDownloaded();
        }
    }

    public void cancel(long id) {
        UploadTask task = getTask(id, true);
        if (task == null) {
            task = getPauseTask(id, true);
            if (task == null) {
                task = getDoingTask(id, false);
                task.downloadThread.cancel();
            }
        }
        if (task.iuploadListener != null) {
            try {
                task.iuploadListener.onCancelUpload(task.position, null, -1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void resume(long id) {
        UploadTask task = getPauseTask(id, true);
        if (task != null) {
            addTask(task);
        }
    }

    public synchronized void setCallback(long id, IuploadListener listener) {
        UploadTask task = getDoingTask(id, false);
        if (task != null) {
            task.iuploadListener = listener;
        } else {
            task = getTask(id, false);
            if (task != null) {
                task.iuploadListener = listener;
            } else {
                task = getPauseTask(id, false);
                if (task != null) {
                    task.iuploadListener = listener;
                }
            }
        }
    }

    private UploadTask getTask(long id, boolean isRemove) {
        for (int i = 0; i < mTasks.size(); i++) {
            UploadTask task = mTasks.get(i);
            //Log.v("uploadtask", "uploadManager getTask ----------------info.id:"+task.id);
            if (task.id == id) {
                //Log.i("uploadtask", "uploadManager getTask exist----------------info.id:"+id);
                if (!isRemove) {
                    return mTasks.get(i);
                } else {
                    return mTasks.remove(i);
                }
            }
        }
        return null;
    }

    private UploadTask getDoingImgTask(String id, boolean isRemove) {
        UploadTask task = mDoingImgTasks.get(id);
        if (task != null) {
            if (isRemove) {
                mDoingImgTasks.remove(id);
            }
            return task;
        }
        return null;
    }

    private UploadTask getDoingTask(long id, boolean isRemove) {
        UploadTask task = mDoingTasks.get(id);
        if (task != null) {
            //Log.v("uploadtask", "uploadManager getDoingTask exist ----------------mDoingTasks size:"+mDoingTasks
            // .size());
            if (isRemove) {
                mDoingTasks.remove(id);
            }
            return task;
        }
        return null;
    }

    private UploadTask getPauseTask(long id, boolean isRemove) {
        UploadTask task = mPauseTasks.get(id);
        if (task != null) {
            if (isRemove) {
                mPauseTasks.remove(id);
            }
            return task;
        }
        return null;
    }

//    public synchronized IUploadCallback getCallback(long id) {
//        UploadTask task = getTask(id, false);
//        if (task != null)
//            return task.uploadCallback;
//        else {
//            task = getDoingTask(id, false);
//            if (task != null) {
//                return task.uploadCallback;
//            } else {
//                task = getPauseTask(id, false);
//                if (task != null) {
//                    return task.uploadCallback;
//                }
//            }
//        }
//        return null;
//    }

    public void setURL_DOWNLOAD(String uRL_DOWNLOAD) {
        URL_DOWNLOAD = uRL_DOWNLOAD;
    }

    public String getURL_DOWNLOAD() {
        return URL_DOWNLOAD;
    }

    class DownloadObserver implements Observer {
        int i = 0;

        public void addObserver(UploadThread download) {
            download.addObserver(this);
        }

        @Override
        public void update(Observable observable, Object data) {
            UploadThread upload = (UploadThread) observable;
            UploadTask task = null;
            switch (upload.getStatus()) {
                case DownConstants.CANCELLED: // cancel status
                    if (!upload.downType) {
                        task = getDoingTask(upload.getId(), true);
                        if (task == null) {
                            task = getPauseTask(upload.getId(), true);
                        }
                        if (task != null) {
                            i = 0;
                            if (task.iuploadListener != null) {
                                task.iuploadListener.onCancelUpload(task.position, upload.getDownloads(),
                                        upload.getCurrentNumber());
                                doTask();
                            }
                        }
                    }
                    break;
                case DownConstants.DOWNLOADING: // downloading status
                    if (!upload.downType) {
                        task = getDoingTask(upload.getId(), false);
                        if (task != null) {
                            if (task.iuploadListener != null) {
                                task.iuploadListener.onUploading(task.position,
                                        upload.getDownloaded(),
                                        upload.getSize(),
                                        upload.getProgress(),
                                        upload.getSpeed(),
                                        upload.getDownloads(),
                                        upload.getCurrentNumber());
                            }
                        }
                    }
                    break;
                case DownConstants.ERROR: // download error status

                    task = getDoingTask(upload.getId(), true);
                    if (task != null) {
                        i = 0;
                        if (upload.getProgress() > 0)
                            mPauseTasks.put(task.id, task);// push suspend task
                        if (task.iuploadListener != null) {
                            task.iuploadListener.onUploadError(task.position,
                                    upload.getDownloaded(), upload.getProgress(),
                                    upload.getDownloads(), upload.getCurrentNumber());
                            doTask();
                            mFileUploadDb.insertOrUpdateMsg(upload.getDownload());
                        }
                    }
                    break;
                case DownConstants.PAUSED: // suspend status
                    if (!upload.downType) {
                        task = getDoingTask(upload.getId(), false);
                        if (task == null) {
                            task = getPauseTask(upload.getId(), false);
                        }
                        if (task != null) {
                            if (task.iuploadListener != null) {
                                task.iuploadListener.onPauseUpload(task.position, upload.getDownloads(),
                                        upload.getCurrentNumber());
                                doTask();
                            }
                        }
                    }
                    break;
                case DownConstants.COMPLETE: // finish status
                    task = getDoingTask(upload.getId(), true);
                    boolean checkFlag = false;
                    if (task != null) {
                        i = 0;
                        if (task.iuploadListener != null) {
                            task.iuploadListener.onUploadAllFinished(task.position, upload.getDownloads(), checkFlag);
                            mFileUploadDb.deleteMsg(upload.getDownload().msgId);
                            doTask();
                        }
                    }
                    break;
            }
        }
    }

    /**
     * @version V1.0.0
     * @ClassName: UploadTask
     * @author:qbluo
     * @Date：2012-8-22
     * @Description: downLoad Task 实体类
     */
    public static class UploadTask {
        public long id;
        public UploadThread downloadThread;
        public IuploadListener iuploadListener;
        public int position;

        public UploadTask(long id) {
            this.id = id;
        }

        public UploadTask(int position, long id,
                          UploadThread downloadThread, IuploadListener iuploadListener) {
            this.id = id;
            this.downloadThread = downloadThread;
            this.iuploadListener = iuploadListener;
            this.position = position;
        }

        @Override
        public boolean equals(Object o) {
            if (id == (((UploadTask) o).id)) {
                return true;
            }
            return false;
        }

    }
}
